<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>如何从0到1构架一个 vue 项目 | Jeffery Blog</title><meta name="keywords" content="vue, vue 最佳实践"><meta name="author" content="志非"><meta name="copyright" content="志非"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="vue, vue 最佳实践">
<meta property="og:type" content="article">
<meta property="og:title" content="如何从0到1构架一个 vue 项目">
<meta property="og:url" content="https://fif.gitee.io/blog/2021/04/09/vue/vue-practice-01/index.html">
<meta property="og:site_name" content="Jeffery Blog">
<meta property="og:description" content="vue, vue 最佳实践">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/FIF/pic-beg/raw/master/images/vue/v2-9098857225d5147df01f9e9a11a8a0ac_1440w.jpg">
<meta property="article:published_time" content="2021-04-08T16:00:00.000Z">
<meta property="article:modified_time" content="2021-04-08T16:00:00.000Z">
<meta property="article:author" content="志非">
<meta property="article:tag" content="vue">
<meta property="article:tag" content="vue 最佳实践">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/FIF/pic-beg/raw/master/images/vue/v2-9098857225d5147df01f9e9a11a8a0ac_1440w.jpg"><link rel="shortcut icon" href="/blog/img/home/avatar.jpeg"><link rel="canonical" href="https://fif.gitee.io/blog/2021/04/09/vue/vue-practice-01/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//fonts.googleapis.com" crossorigin=""/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/blog/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.js" defer></script><script async="async" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><script>(adsbygoogle = window.adsbygoogle || []).push({
  google_ad_client: '',
  enable_page_level_ads: 'true'
});</script><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Titillium+Web&amp;display=swap" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/blog/',
  algolia: {"appId":"QYKLQ4BSGP","apiKey":"d45fc66694b4260b20711a30fdb5c4e1","indexName":"jeffery-blog","hits":{"per_page":6},"languages":{"input_placeholder":"搜索文章","hits_empty":"找不到您查询的内容：${query}","hits_stats":"找到 ${hits} 条结果，用时 ${time} 毫秒"}},
  localSearch: undefined,
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
  noticeOutdate: {"limitDay":200,"position":"top","messagePrev":"本文修改于","messageNext":"天前，如果本文有一定的时效性，那么本文可能已经失效~"},
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'mediumZoom',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#121212","position":"bottom-left"},
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = { 
  isPost: true,
  isHome: false,
  isHighlightShrink: true,
  isToc: true,
  postUpdate: '2021-04-09 00:00:00'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    })(window)</script><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/blog/atom.xml" title="Jeffery Blog" type="application/atom+xml">
</head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><img class="load-image" src= "" data-lazy-src="/blog/img/loading.gif" alt=""/></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" src= "" data-lazy-src="/blog/img/home/avatar.jpeg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">12</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">6</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">7</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/blog/"><i class="fa-fw fa fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/blog/archives/"><i class="fa-fw fa fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/blog/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/blog/categories/"><i class="fa-fw fa fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 媒体</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/blog/books/"><i class="fa-fw fas fa-book"></i><span> 阅读</span></a></li><li><a class="site-page child" href="/blog/music/"><i class="fa-fw fa fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/blog/movies/"><i class="fa-fw fa fa-film"></i><span> 电影</span></a></li><li><a class="site-page child" href="/blog/gallery/"><i class="fa-fw far fa-image"></i><span> 相册</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/blog/box/"><i class="fa-fw fab fa-xbox"></i><span> 聚宝盒</span></a></div><div class="menus_item"><a class="site-page" href="/blog/talk/"><i class="fa-fw far fa-comment"></i><span> 微语</span></a></div><div class="menus_item"><a class="site-page" href="/blog/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/blog/about/"><i class="fa-fw fa fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://gitee.com/FIF/pic-beg/raw/master/images/vue/v2-9098857225d5147df01f9e9a11a8a0ac_1440w.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/blog/">Jeffery Blog</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/blog/"><i class="fa-fw fa fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/blog/archives/"><i class="fa-fw fa fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/blog/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/blog/categories/"><i class="fa-fw fa fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 媒体</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/blog/books/"><i class="fa-fw fas fa-book"></i><span> 阅读</span></a></li><li><a class="site-page child" href="/blog/music/"><i class="fa-fw fa fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/blog/movies/"><i class="fa-fw fa fa-film"></i><span> 电影</span></a></li><li><a class="site-page child" href="/blog/gallery/"><i class="fa-fw far fa-image"></i><span> 相册</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/blog/box/"><i class="fa-fw fab fa-xbox"></i><span> 聚宝盒</span></a></div><div class="menus_item"><a class="site-page" href="/blog/talk/"><i class="fa-fw far fa-comment"></i><span> 微语</span></a></div><div class="menus_item"><a class="site-page" href="/blog/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/blog/about/"><i class="fa-fw fa fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">如何从0到1构架一个 vue 项目</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-04-08T16:00:00.000Z" title="发表于 2021-04-09 00:00:00">2021-04-09</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2021-04-08T16:00:00.000Z" title="更新于 2021-04-09 00:00:00">2021-04-09</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/%E5%89%8D%E7%AB%AF/">前端</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/blog/categories/%E5%89%8D%E7%AB%AF/vue/">vue</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">2.9k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>12分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="如何从0到1构架一个 vue 项目"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="vue-cli-脚手架搭建项目"><a href="#vue-cli-脚手架搭建项目" class="headerlink" title="vue-cli 脚手架搭建项目"></a>vue-cli 脚手架搭建项目</h2><p>用 <a target="_blank" rel="noopener" href="https://cli.vuejs.org/">vue-cli</a> 搭建项目，规范设计目录结构和框架</p>
<h3 id="目录结构设计"><a href="#目录结构设计" class="headerlink" title="目录结构设计"></a>目录结构设计</h3><ul>
<li>视图页面放在 pages 或者 views 中</li>
<li>静态文件放在 static 中</li>
<li>资源文件放在 assets 中</li>
<li>样式文件放在 styles 中</li>
<li>辅助库放在 utils 中</li>
<li>配置文件可以放在 config 或者 constants 中</li>
<li>vuex 的文件放在 stores 中，至于 getters, actions, mutation, modules 可以参考 <a target="_blank" rel="noopener" href="https://vuex.vuejs.org/zh/guide/">vuex</a> 的文档</li>
<li>路由文件放在 routes 中</li>
<li>共用组件放在 components 中</li>
<li>共享代码也可以使用shared作为目录</li>
<li>布局组件可以放在layouts目录中</li>
</ul>
<h3 id="项目用到的库"><a href="#项目用到的库" class="headerlink" title="项目用到的库"></a>项目用到的库</h3><p><strong>UI框架</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN">Element</a></li>
<li><a target="_blank" rel="noopener" href="https://www.iviewui.com/">iView</a></li>
<li><a target="_blank" rel="noopener" href="https://antdv.com/docs/vue/introduce-cn/">Ant Design Vue</a></li>
<li>……</li>
</ul>
<blockquote>
<p>注：UI风格目前有 <a target="_blank" rel="noopener" href="https://getbootstrap.com/">Bookstrap</a>、<a target="_blank" rel="noopener" href="https://ant.design/index-cn">Antd</a> 和 <a target="_blank" rel="noopener" href="https://material.io/design">Google Materials</a> 三种风格，在项目搭建时这也是一个很重要的技术选型。</p>
</blockquote>
<p><strong>日期库</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://github.com/iamkun/dayjs/">dayjs</a></li>
<li><a target="_blank" rel="noopener" href="https://momentjs.com/">moment</a> （文件体积大）</li>
</ul>
<p><strong>图表</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/index.html">echarts</a></li>
<li><a target="_blank" rel="noopener" href="https://www.highcharts.com/">highcharts</a></li>
<li><a target="_blank" rel="noopener" href="https://antv.vision/zh">AntV 可视化</a></li>
</ul>
<p><strong>工具库</strong></p>
<ul>
<li>URL解析: <a target="_blank" rel="noopener" href="https://github.com/sindresorhus/query-string">query-string</a>、<a target="_blank" rel="noopener" href="https://github.com/pillarjs/path-to-regexp">path-to-reqexp</a></li>
<li>实用方法：<a target="_blank" rel="noopener" href="https://lodash.com/">lodash</a></li>
<li>接口库：<a target="_blank" rel="noopener" href="https://github.com/axios/axios">axios</a>、<a target="_blank" rel="noopener" href="https://github.com/matthew-andrews/isomorphic-fetch">isomorphic-fetch</a>、<a target="_blank" rel="noopener" href="https://github.com/matthew-andrews/isomorphic-fetch">fetch</a></li>
<li>Meta修改：<a target="_blank" rel="noopener" href="https://github.com/nuxt/vue-meta">vue-meta</a></li>
<li>cookie 操作：<a target="_blank" rel="noopener" href="https://github.com/js-cookie/js-cookie">js-cookie</a></li>
<li>混淆ID: <a target="_blank" rel="noopener" href="https://github.com/vinkla/hashids">hashids</a></li>
</ul>
<p><strong>拖拽</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://github.com/SortableJS/Vue.Draggable">Vue.Draggable</a></li>
</ul>
<h3 id="规范设计"><a href="#规范设计" class="headerlink" title="规范设计"></a>规范设计</h3><p><strong>接口设计</strong></p>
<ul>
<li>封装 axios ，统一 api 调用风格和基本配置</li>
</ul>
<p><strong>环境测试</strong></p>
<ul>
<li>开放、测试和正式环境配置，一般不同环境接口基础路径不一样</li>
</ul>
<h3 id="代理和数据Mock"><a href="#代理和数据Mock" class="headerlink" title="代理和数据Mock"></a>代理和数据Mock</h3><ul>
<li><a target="_blank" rel="noopener" href="https://www.adcisolutions.com/knowledge/how-build-single-page-application-spa-vuejs">SPA</a> 页面开发通常都是配置代码来调用后端的接口数据，怎么配置可以参考@vue/cli文档。数据 Mock 主要用到一个 <a target="_blank" rel="noopener" href="http://mockjs.com/">mockjs</a> </li>
</ul>
<h3 id="持续集成和部署"><a href="#持续集成和部署" class="headerlink" title="持续集成和部署"></a>持续集成和部署</h3><ul>
<li>目前开源项目通常采用 <a target="_blank" rel="noopener" href="https://travis-ci.org/">Travis</a>，而一般公司内部项目通常采用 <a target="_blank" rel="noopener" href="https://www.jenkins.io/zh/">Jenkins</a> 来做持续集成，在部署上通常采用 <a target="_blank" rel="noopener" href="https://docs.docker.com/">Docker</a>，集群上使用 <a target="_blank" rel="noopener" href="https://github.com/KubeOperator/KubeOperator">KubeOperator</a> 来管理。</li>
</ul>
<p><strong>API请求方式</strong></p>
<ul>
<li>通常采用 <a target="_blank" rel="noopener" href="https://github.com/aisuhua/restful-api-design-references">Restful</a> 的方式来请求数据，也可以采用 <a target="_blank" rel="noopener" href="https://graphql.org/">GraphQL</a> 的方式来请求。如果采用Restfull的方式通常可以使用 axios, fetch api。GraphQL 可以使用 <a target="_blank" rel="noopener" href="https://www.apollographql.com/docs/react/">Apollo Client</a></li>
</ul>
<h3 id="项目文档和组件测试文档"><a href="#项目文档和组件测试文档" class="headerlink" title="项目文档和组件测试文档"></a>项目文档和组件测试文档</h3><ul>
<li>除了在项目根目录放一个 <code>README.MD</code> 文件外，通常还需要一些比如 <code>CHANGELOG.md</code>, <code>PLAD.md</code> 等文档，还有一些组件的使用文档，可以考虑使用 <code>styleguide</code>和 <code>storybook</code> 。</li>
</ul>
<h2 id="基于-vue-cli的选型"><a href="#基于-vue-cli的选型" class="headerlink" title="基于@vue/cli的选型"></a>基于@vue/cli的选型</h2><p><strong>ES6/7 or Typescript</strong></p>
<ul>
<li>鉴于目前Typescript如此流行，很多流行的框架和库都采用其来写，IDE友好的智能提示、强类型结束等，在立项时是否考虑采用Typescript来写Vue项目</li>
</ul>
<p><strong>Sass/Less/Stylus/PostCss ?</strong></p>
<ul>
<li>由于 Vue 项目开发本身样式自带 scope，所以不需要像 React 那样去选 css-in-js 框架（目前在 React 最流行的是 styled-components），但是如果我们在Vue中采用JSX的方式来定义组件，是否考虑引入vue-styled-components这个库（年久失修，完全脱节React版了，但依然是Vue中最好的选择）。在Vue中sass, less, stylus可以在 <code>&lt;style&gt;</code> 标签中通过lang=””来指定，如果你想使用PostCss也可以的，就是要自己花点时间去折腾一下。</li>
</ul>
<p><strong>关于代码规范和风格</strong></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://prettier.io/">Prettier</a> </li>
<li><a target="_blank" rel="noopener" href="https://google.github.io/styleguide/jsguide.html">Google JavaScript Style Guide</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/airbnb/javascript">Airbnb JavaScript Style Guide</a></li>
</ul>
<p><strong>关于测试</strong></p>
<ul>
<li>单元测试 <a target="_blank" rel="noopener" href="https://www.guru99.com/unit-testing-guide.html">Unit Testing</a> </li>
<li>端到端测试 <a target="_blank" rel="noopener" href="https://www.katalon.com/resources-center/blog/end-to-end-e2e-testing/">E2E Testing</a></li>
</ul>
<h2 id="项目类型"><a href="#项目类型" class="headerlink" title="项目类型"></a>项目类型</h2><h3 id="小程序"><a href="#小程序" class="headerlink" title="小程序"></a>小程序</h3><ul>
<li>框架限定使用 <a target="_blank" rel="noopener" href="https://vuejs.org/index.html">Vue</a>, 例如 <a target="_blank" rel="noopener" href="http://mpvue.com/">mpvue</a>、<a target="_blank" rel="noopener" href="https://uniapp.dcloud.io/">uni-app</a></li>
</ul>
<h3 id="H5-页面"><a href="#H5-页面" class="headerlink" title="H5 页面"></a>H5 页面</h3><ul>
<li>微信页面、<a target="_blank" rel="noopener" href="https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html">Webview</a> 中的 H5 页面</li>
</ul>
<h3 id="PC-官网"><a href="#PC-官网" class="headerlink" title="PC 官网"></a>PC 官网</h3><ul>
<li>主要是用来展示企业信息、产品，对交互、体验有一定的要求，会有一些炫酷的动画效果。还有就是官网有可能需要采用 SSR（比如 <a target="_blank" rel="noopener" href="https://vuejs.org/index.html">Vue</a> 的 <a target="_blank" rel="noopener" href="https://nuxtjs.org/">Nuxt.js</a>）来做，来确定良好的 SEO。</li>
</ul>
<h3 id="后台管理系统"><a href="#后台管理系统" class="headerlink" title="后台管理系统"></a>后台管理系统</h3><ul>
<li>后台管理系统主要功能在于数据的配置、权限的控制、数据报表的展示、日志功能等。通常又叫 CMS，OA</li>
</ul>
<h3 id="Native开发"><a href="#Native开发" class="headerlink" title="Native开发"></a>Native开发</h3><ul>
<li>通常就是指用前端技术去开发 PC 应用、APP 应用，比如 <a target="_blank" rel="noopener" href="https://weex.apache.org/zh/guide/introduction.html">Weex</a>, <a target="_blank" rel="noopener" href="https://www.electronjs.org/">Electron</a>。</li>
</ul>
<h2 id="版本管理"><a href="#版本管理" class="headerlink" title="版本管理"></a>版本管理</h2><p><strong>Git Flow</strong></p>
<ul>
<li><p>在开发环境的区分上通常分为生产（线上）环境、预发布环境、开发环境，有的还有什么沙盒环境，很多做得好的公司基于Docker前后端都可以根据每一个commit来发布。</p>
</li>
<li><p>有时候不想把有些代码提交上去，除了选择性提交单个文件外，还有使用git的stash功能，此外如果使用Webstorm可还可以使用其提供的Changelist来缓存修改，切换分支。</p>
</li>
</ul>
<p><strong>Git Comit</strong></p>
<p>项目提交的描述如果没有一定的规范，随性而为的话，就会让其它人误解。通常提交采用英文作为描述，可以多行文字。在社区中有很多流行的方案(比如 <a target="_blank" rel="noopener" href="https://www.conventionalcommits.org/en/v1.0.0/">Conventional Commit</a>)，更多的是采用Angular的方式</p>
<p><strong>Change Log</strong></p>
<p>如果采用了社区统一的commit方式，那么我们就可以基于提交来生成变更记录，在每一次版本发布时自动关联Jira中的Issue。</p>
<p><strong>版本号生成</strong></p>
<p>这个通常是按照 <a target="_blank" rel="noopener" href="https://semver.org/">Semantic Versioning</a> 的规范来打tag，具休怎么做可以自行尝试</p>
<p>在项目中通常使用gitHooks和husky这二个node包来配置上面提到的这些。在git钩子中我们在每次提交、push前跑一次单元测试、代码覆盖率。前端代码覆盖率一般来说没有必要加，不然很痛苦。</p>
<p>下面是package.json文件中相关的配置示例（试验性代码）</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;your-project-name&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;version&quot;</span>: <span class="string">&quot;0.1.0&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;scripts&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;clean&quot;</span>: <span class="string">&quot;rm -rf node_modules&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;serve&quot;</span>: <span class="string">&quot;vue-cli-service serve&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;build&quot;</span>: <span class="string">&quot;vue-cli-service build&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;lint&quot;</span>: <span class="string">&quot;vue-cli-service lint --no-fix&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;stylelint&quot;</span>: <span class="string">&quot;stylelint src/**/*.&#123;scss,css,less,css,vue,jsx&#125; --fix&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;eslint&quot;</span>: <span class="string">&quot;eslint --ext .js,.jsx,.vue src --fix&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;changelog&quot;</span>: <span class="string">&quot;conventional-changelog -p angular -i CHANGELOG.md -s -r 0&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;repository&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;type&quot;</span>: <span class="string">&quot;git&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;url&quot;</span>: <span class="string">&quot;http://gitlab.transsion.com/mi/mi-bigdata-admin.git&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;dependencies&quot;</span>: &#123;&#125;,</span><br><span class="line">  <span class="attr">&quot;devDependencies&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;@commitlint/cli&quot;</span>: <span class="string">&quot;^8.1.0&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;@commitlint/config-conventional&quot;</span>: <span class="string">&quot;^8.1.0&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;babel-eslint&quot;</span>: <span class="string">&quot;^10.0.1&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;conventional-changelog-cli&quot;</span>: <span class="string">&quot;^2.0.23&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;eslint&quot;</span>: <span class="string">&quot;^6.2.1&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;eslint-plugin-vue&quot;</span>: <span class="string">&quot;^5.2.3&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;husky&quot;</span>: <span class="string">&quot;^3.0.4&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;lint-staged&quot;</span>: <span class="string">&quot;^9.2.3&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;stylelint&quot;</span>: <span class="string">&quot;^10.1.0&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;stylelint-config-standard&quot;</span>: <span class="string">&quot;^18.3.0&quot;</span>,</span><br><span class="line">    <span class="attr">&quot;stylelint-scss&quot;</span>: <span class="string">&quot;^3.9.4&quot;</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;gitHooks&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;pre-commit&quot;</span>: <span class="string">&quot;lint-staged&quot;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;lint-staged&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;*.&#123;js,vue&#125;&quot;</span>: [</span><br><span class="line">      <span class="string">&quot;vue-cli-service lint&quot;</span>,</span><br><span class="line">      <span class="string">&quot;eslint --fix --ext .js,.vue src&quot;</span>,</span><br><span class="line">      <span class="string">&quot;git add&quot;</span></span><br><span class="line">    ],</span><br><span class="line">    <span class="attr">&quot;*.&#123;css,scss,less,vue&#125;&quot;</span>: [</span><br><span class="line">      <span class="string">&quot;stylelint --fix&quot;</span>,</span><br><span class="line">      <span class="string">&quot;git add&quot;</span></span><br><span class="line">    ]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">&quot;husky&quot;</span>: &#123;</span><br><span class="line">    <span class="attr">&quot;hooks&quot;</span>: &#123;</span><br><span class="line">      <span class="attr">&quot;commit-msg&quot;</span>: <span class="string">&quot;commitlint -E HUSKY_GIT_PARAMS&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="通用配置"><a href="#通用配置" class="headerlink" title="通用配置"></a>通用配置</h2><p> <strong>编辑器配置</strong>：<code>.editorconfig</code></p>
<p>这里最重要的是缩进方式，及Tab大小，建议2个空格作用缩进。</p>
<figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"># https://editorconfig.org</span><br><span class="line">root = true</span><br><span class="line"></span><br><span class="line">[*]</span><br><span class="line">charset = utf-8</span><br><span class="line">indent_style = space</span><br><span class="line">indent_size = 2</span><br><span class="line">end_of_line = lf</span><br><span class="line">insert_final_newline = true</span><br><span class="line">trim_trailing_whitespace = true</span><br><span class="line"></span><br><span class="line">[*.md]</span><br><span class="line">insert_final_newline = false</span><br><span class="line">trim_trailing_whitespace = false</span><br></pre></td></tr></table></figure>

<p> <strong>Git忽略文件配置</strong>: <code>.gitignore</code></p>
<p>这里的配置决定了哪些文件会被版本控制所忽略</p>
<figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"># See https://help.github.com/articles/ignoring-files/ for more about ignoring files.</span><br><span class="line"></span><br><span class="line"># dependencies</span><br><span class="line">/node_modules</span><br><span class="line">/.pnp</span><br><span class="line">.pnp.js</span><br><span class="line"></span><br><span class="line"># testing</span><br><span class="line">/coverage</span><br><span class="line"></span><br><span class="line"># production</span><br><span class="line">/build</span><br><span class="line"></span><br><span class="line"># misc</span><br><span class="line">.DS_Store</span><br><span class="line">.env.local</span><br><span class="line">.env.development.local</span><br><span class="line">.env.test.local</span><br><span class="line">.env.production.local</span><br><span class="line"></span><br><span class="line">npm-debug.log*</span><br><span class="line">yarn-debug.log*</span><br><span class="line">yarn-error.log*</span><br><span class="line"></span><br><span class="line"># editor</span><br><span class="line">/.idea</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p><strong>Eslint配置</strong>: <code>.eslintrc.js</code>，<code>.eslintignore</code> 等</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br></pre></td><td class="code"><pre><span class="line">module.exports = &#123;</span><br><span class="line">  root: true,</span><br><span class="line">  env: &#123;</span><br><span class="line">    node: true</span><br><span class="line">  &#125;,</span><br><span class="line">  extends: [&quot;plugin:vue/strongly-recommended&quot;],</span><br><span class="line">  rules: &#123;</span><br><span class="line">    &quot;no-console&quot;: process.env.NODE_ENV === &quot;production&quot; ? &quot;error&quot; : &quot;off&quot;,</span><br><span class="line">    &quot;no-debugger&quot;: process.env.NODE_ENV === &quot;production&quot; ? &quot;error&quot; : &quot;off&quot;,</span><br><span class="line">    <span class="comment">// 不加分号</span></span><br><span class="line">    &quot;semi&quot;: [0],</span><br><span class="line">    <span class="comment">// 不能有未定义的变量</span></span><br><span class="line">    &quot;no-undef&quot;: 1,</span><br><span class="line">    <span class="comment">// 不能有声明后未被使用的变量或参数</span></span><br><span class="line">    &quot;no-unused-vars&quot;:[2, &#123;</span><br><span class="line">      &quot;vars&quot;: &quot;local&quot;,</span><br><span class="line">      &quot;args&quot;: &quot;none&quot;</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// 禁止修改const声明的变量</span></span><br><span class="line">    &quot;no-const-assign&quot;: 2,</span><br><span class="line">    <span class="comment">// 函数参数不能重复</span></span><br><span class="line">    &quot;no-dupe-args&quot;: 2,</span><br><span class="line">    <span class="comment">// 如果if语句里面有return,后面不能跟else语句</span></span><br><span class="line">    &quot;no-else-return&quot;: 2,</span><br><span class="line">    <span class="comment">// 块语句中的内容不能为空</span></span><br><span class="line">    &quot;no-empty&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止对null使用==或!=运算符</span></span><br><span class="line">    &quot;no-eq-null&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止扩展native对象</span></span><br><span class="line">    &quot;no-extend-native&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止不必要的函数绑定</span></span><br><span class="line">    &quot;no-extra-bind&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止非必要的括号</span></span><br><span class="line">    &quot;no-extra-parens&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止多余的冒号</span></span><br><span class="line">    &quot;no-extra-semi&quot;:2,</span><br><span class="line">    <span class="comment">// 禁止省略浮点数中的0 .5 3.</span></span><br><span class="line">    &quot;no-floating-decimal&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止行内备注</span></span><br><span class="line">    &quot;no-inline-comments&quot;: 0,</span><br><span class="line">    <span class="comment">// 不能有不规则的空格</span></span><br><span class="line">    &quot;no-irregular-whitespace&quot;: 2,</span><br><span class="line">    <span class="comment">// 不能用多余的空格</span></span><br><span class="line">    &quot;no-multi-spaces&quot;: 1,</span><br><span class="line">    <span class="comment">// 禁止重复声明变量</span></span><br><span class="line">    &quot;no-redeclare&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止使用javascript:void(0)</span></span><br><span class="line">    &quot;no-script-url&quot;: 0,</span><br><span class="line">    <span class="comment">// 禁止稀疏数组， [0,,2]</span></span><br><span class="line">    &quot;no-sparse-arrays&quot;: 2,</span><br><span class="line">    <span class="comment">// 禁止使用三目运算符</span></span><br><span class="line">    &quot;no-ternary&quot;: 0,</span><br><span class="line">    <span class="comment">// 一行结束后面不要有空格</span></span><br><span class="line">    &quot;no-trailing-spaces&quot;: 1,</span><br><span class="line">    <span class="comment">// 标识符不能以_开头或结尾</span></span><br><span class="line">    &quot;no-underscore-dangle&quot;: 1,</span><br><span class="line">    <span class="comment">// 是否允许非空数组里面有多余的空格</span></span><br><span class="line">    &quot;array-bracket-spacing&quot;: [2, &quot;never&quot;],</span><br><span class="line">    <span class="comment">// 箭头函数用小括号括起来</span></span><br><span class="line">    &quot;arrow-parens&quot;: 0,</span><br><span class="line">    <span class="comment">// =&gt;的前/后括号</span></span><br><span class="line">    &quot;arrow-spacing&quot;: 0,</span><br><span class="line">    <span class="comment">// 块语句中使用var</span></span><br><span class="line">    &quot;block-scoped-var&quot;: 0,</span><br><span class="line">    <span class="comment">// 逗号风格，换行时在行首还是行尾</span></span><br><span class="line">    &quot;comma-style&quot;: [2, &quot;last&quot;],</span><br><span class="line">    <span class="comment">// 避免不必要的方括号</span></span><br><span class="line">    &quot;dot-notation&quot;: [0, &#123; &quot;allowKeywords&quot;: true &#125;],</span><br><span class="line">    <span class="comment">// 必须使用全等</span></span><br><span class="line">    &quot;eqeqeq&quot;: 2,</span><br><span class="line">    <span class="comment">// 对象字面量中冒号的前后空格</span></span><br><span class="line">    &quot;key-spacing&quot;: [0, &#123;</span><br><span class="line">      &quot;beforeColon&quot;: false,</span><br><span class="line">      &quot;afterColon&quot;: true</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// 变量声明后是否需要空一行</span></span><br><span class="line">    &quot;newline-after-var&quot;: 0,</span><br><span class="line">    <span class="comment">// 引号类型 `` &quot;&quot; &#x27;&#x27;</span></span><br><span class="line">    &quot;quotes&quot;: [1, &quot;single&quot;],</span><br><span class="line">    <span class="comment">// 变量声明时排序</span></span><br><span class="line">    &quot;sort-vars&quot;: 0,</span><br><span class="line">    <span class="comment">// 禁止比较时使用NaN，只能用isNaN()</span></span><br><span class="line">    &quot;use-isnan&quot;: 2,</span><br><span class="line">    <span class="comment">//jsx中使用单引号</span></span><br><span class="line">    &quot;jsx-quotes&quot;: [&quot;error&quot;, &quot;prefer-single&quot;],</span><br><span class="line">    <span class="comment">// 单个组件无内容自结尾</span></span><br><span class="line">    &quot;vue/html-self-closing&quot;: [&quot;error&quot;, &#123;</span><br><span class="line">      &quot;html&quot;: &#123;</span><br><span class="line">        &quot;void&quot;: &quot;always&quot;,</span><br><span class="line">        &quot;normal&quot;: &quot;always&quot;,</span><br><span class="line">        &quot;component&quot;: &quot;always&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;svg&quot;: &quot;always&quot;,</span><br><span class="line">      &quot;math&quot;: &quot;always&quot;</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// 设置html缩进</span></span><br><span class="line">    &quot;vue/html-indent&quot;: [&quot;error&quot;, 2, &#123;</span><br><span class="line">      &quot;attribute&quot;: 2,</span><br><span class="line">      &quot;baseIndent&quot;: 1,</span><br><span class="line">      &quot;closeBracket&quot;: 0,</span><br><span class="line">      &quot;alignAttributesVertically&quot;: false,</span><br><span class="line">      &quot;ignores&quot;: []</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// 属性顺序</span></span><br><span class="line">    &quot;vue/attributes-order&quot;: 1,</span><br><span class="line">    <span class="comment">// 注释前面需要添加空格</span></span><br><span class="line">    &quot;spaced-comment&quot;: [&quot;error&quot;, &quot;always&quot;, &#123; &quot;exceptions&quot;: [&quot;-&quot;, &quot;+&quot;] &#125;],</span><br><span class="line">    <span class="comment">// html属性赋值等号左右不能有空格</span></span><br><span class="line">    &quot;vue/no-spaces-around-equal-signs-in-attribute&quot;: [&quot;error&quot;],</span><br><span class="line">    <span class="comment">// 强制prop以驼峰命名</span></span><br><span class="line">    &quot;vue/prop-name-casing&quot;: [&quot;error&quot;, &quot;camelCase&quot;],</span><br><span class="line">    <span class="comment">// 移除多余不使用的空格</span></span><br><span class="line">    &quot;vue/no-multi-spaces&quot;: [&quot;error&quot;, &#123;</span><br><span class="line">      &quot;ignoreProperties&quot;: false</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// html结尾 &gt;</span></span><br><span class="line">    &quot;vue/html-closing-bracket-newline&quot;: [&quot;error&quot;, &#123;</span><br><span class="line">      &quot;singleline&quot;: &quot;never&quot;,</span><br><span class="line">      &quot;multiline&quot;: &quot;never&quot;</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// 属性每行数量</span></span><br><span class="line">    &quot;vue/max-attributes-per-line&quot;: [&quot;error&quot;, &#123;</span><br><span class="line">      <span class="comment">// 一行最多3个属性</span></span><br><span class="line">     &quot;singleline&quot;: 3,</span><br><span class="line">      &quot;multiline&quot;: &#123;</span><br><span class="line">        &quot;max&quot;: 1,</span><br><span class="line">        &quot;allowFirstLine&quot;: true</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;],</span><br><span class="line">    <span class="comment">// 单行html元素内容是否换行</span></span><br><span class="line">    &quot;vue/singleline-html-element-content-newline&quot;: [&quot;error&quot;, &#123;</span><br><span class="line">      &quot;ignoreWhenNoAttributes&quot;: true,</span><br><span class="line">      &quot;ignoreWhenEmpty&quot;: true,</span><br><span class="line">      &quot;ignores&quot;: [</span><br><span class="line">        &quot;pre&quot;,</span><br><span class="line">        &quot;textarea&quot;,</span><br><span class="line">        &quot;span&quot;,</span><br><span class="line">        &quot;i&quot;,</span><br><span class="line">        &quot;label&quot;,</span><br><span class="line">        &quot;el-button&quot;,</span><br><span class="line">        &quot;el-radio&quot;,</span><br><span class="line">        &quot;el-checkbox&quot;,</span><br><span class="line">        &quot;el-link&quot;,</span><br><span class="line">        &quot;el-tab-pane&quot;,</span><br><span class="line">        &quot;el-dropdown-item&quot;,</span><br><span class="line">        &quot;el-step&quot;,</span><br><span class="line">        &quot;el-table-column&quot;,</span><br><span class="line">        <span class="string">&quot;el-option&quot;</span></span><br><span class="line">      ]</span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  parserOptions: &#123;</span><br><span class="line">    parser: &quot;babel-eslint&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p><strong>PostCss 配置</strong>: <code>postcss.config.js</code></p>
<p>这个文件自动生成，里面的内容就是指定 <code>autoprefixer</code> 兼容配置</p>
<p><strong>Babel配置</strong>:  <code>babel.config.js</code></p>
<p>主要是配置 <code>Babel</code> 的 <code>plugins</code>、<code>presets</code> 和 <code>parse</code> 等</p>
<p><strong>Webpack</strong> 配置：<code>webpack.config.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">resolve</span> (<span class="params">dir</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> path.join(__dirname, <span class="string">&#x27;.&#x27;</span>, dir)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">  context: path.resolve(__dirname, <span class="string">&#x27;./&#x27;</span>),</span><br><span class="line">  resolve: &#123;</span><br><span class="line">    extensions: [<span class="string">&#x27;.js&#x27;</span>, <span class="string">&#x27;.vue&#x27;</span>, <span class="string">&#x27;.json&#x27;</span>],</span><br><span class="line">    alias: &#123;</span><br><span class="line">      <span class="string">&#x27;@&#x27;</span>: resolve(<span class="string">&#x27;src&#x27;</span>),</span><br><span class="line">      <span class="string">&#x27;_c&#x27;</span>: resolve(<span class="string">&#x27;src/components&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul>
<li><a target="_blank" rel="noopener" href="https://guide.aotu.io/index.html">Front-End Coding Guidelines</a></li>
<li><a target="_blank" rel="noopener" href="https://wdd.js.org/js-best-practices/#/">JS最佳实践</a></li>
</ul>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">志非</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://fif.gitee.io/blog/2021/04/09/vue/vue-practice-01/">https://fif.gitee.io/blog/2021/04/09/vue/vue-practice-01/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://fif.gitee.io/blog" target="_blank">Jeffery Blog</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/blog/tags/vue/">vue</a><a class="post-meta__tags" href="/blog/tags/vue-%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/">vue 最佳实践</a></div><div class="post_share"><div class="social-share" data-image="https://gitee.com/FIF/pic-beg/raw/master/images/vue/v2-9098857225d5147df01f9e9a11a8a0ac_1440w.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-full"><a href="/blog/2021/04/10/vue/vue-code-1.package/"><img class="prev-cover" src= "" data-lazy-src="https://pic4.zhimg.com/v2-f3cb85d3ca5d58e80142a58e4cdb2c57_1440w.jpg?source=172ae18b" onerror="onerror=null;src='/blog/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">package.json 属性详解</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span> 相关推荐</span></div><div class="relatedPosts-list"><div><a href="/blog/2021/04/10/vue/vue-code-1.package/" title="package.json 属性详解"><img class="cover" src= "" data-lazy-src="https://pic4.zhimg.com/v2-f3cb85d3ca5d58e80142a58e4cdb2c57_1440w.jpg?source=172ae18b" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-10</div><div class="title">package.json 属性详解</div></div></a></div><div><a href="/blog/2021/04/11/vue/vue-code-2.rollup/" title="rollup 教程"><img class="cover" src= "" data-lazy-src="https://www.rollupjs.com/img/twitter-card.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-11</div><div class="title">rollup 教程</div></div></a></div><div><a href="/blog/2021/04/12/vue/vue-code-3.build/" title="（Vue源码一）Vue 源码设计和构建流程"><img class="cover" src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/Vue.js-i18n-768x512.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-12</div><div class="title">（Vue源码一）Vue 源码设计和构建流程</div></div></a></div><div><a href="/blog/2021/04/17/vue/vue-code-4.debugger/" title="（Vue源码二）Vue实例挂载流程"><img class="cover" src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/1_b2Ig4HR2UOQEV5I2QnQrrw.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-17</div><div class="title">（Vue源码二）Vue实例挂载流程</div></div></a></div><div><a href="/blog/2021/04/23/vue/vue-code-5.mergeOptions/" title="（Vue源码三）Vue 丰富的选项合并策略"><img class="cover" src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/vue-highcharts_1200.webp" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-23</div><div class="title">（Vue源码三）Vue 丰富的选项合并策略</div></div></a></div><div><a href="/blog/2021/04/30/vue/vue-code-7-compiler/" title="（Vue源码五）Vue 编译原理"><img class="cover" src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/vuetemplate.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-04-30</div><div class="title">（Vue源码五）Vue 编译原理</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div class="vcomment" id="vcomment"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-avatar is-center"><img class="avatar-img" src= "" data-lazy-src="/blog/img/home/avatar.jpeg" onerror="this.onerror=null;this.src='/blog/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">志非</div><div class="author-info__description">自己变得更好，生活才会更美好</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/blog/archives/"><div class="headline">文章</div><div class="length-num">12</div></a></div><div class="card-info-data-item is-center"><a href="/blog/tags/"><div class="headline">标签</div><div class="length-num">6</div></a></div><div class="card-info-data-item is-center"><a href="/blog/categories/"><div class="headline">分类</div><div class="length-num">7</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/JefferyXZF"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/JefferyXZF" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="https://www.yuque.com/jeffery-kkrpn/uz24n9" target="_blank" title="语雀"><i class="fa fa-folder-open"></i></a><a class="social-icon" href="https://mail.qq.com/" target="_blank" title="Email"><i class="fas fa-envelope"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">越努力越幸运</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#vue-cli-%E8%84%9A%E6%89%8B%E6%9E%B6%E6%90%AD%E5%BB%BA%E9%A1%B9%E7%9B%AE"><span class="toc-number">1.</span> <span class="toc-text">vue-cli 脚手架搭建项目</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84%E8%AE%BE%E8%AE%A1"><span class="toc-number">1.1.</span> <span class="toc-text">目录结构设计</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E7%94%A8%E5%88%B0%E7%9A%84%E5%BA%93"><span class="toc-number">1.2.</span> <span class="toc-text">项目用到的库</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A7%84%E8%8C%83%E8%AE%BE%E8%AE%A1"><span class="toc-number">1.3.</span> <span class="toc-text">规范设计</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%A3%E7%90%86%E5%92%8C%E6%95%B0%E6%8D%AEMock"><span class="toc-number">1.4.</span> <span class="toc-text">代理和数据Mock</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90%E5%92%8C%E9%83%A8%E7%BD%B2"><span class="toc-number">1.5.</span> <span class="toc-text">持续集成和部署</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E6%96%87%E6%A1%A3%E5%92%8C%E7%BB%84%E4%BB%B6%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3"><span class="toc-number">1.6.</span> <span class="toc-text">项目文档和组件测试文档</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E-vue-cli%E7%9A%84%E9%80%89%E5%9E%8B"><span class="toc-number">2.</span> <span class="toc-text">基于@vue&#x2F;cli的选型</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E7%B1%BB%E5%9E%8B"><span class="toc-number">3.</span> <span class="toc-text">项目类型</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B0%8F%E7%A8%8B%E5%BA%8F"><span class="toc-number">3.1.</span> <span class="toc-text">小程序</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#H5-%E9%A1%B5%E9%9D%A2"><span class="toc-number">3.2.</span> <span class="toc-text">H5 页面</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#PC-%E5%AE%98%E7%BD%91"><span class="toc-number">3.3.</span> <span class="toc-text">PC 官网</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F"><span class="toc-number">3.4.</span> <span class="toc-text">后台管理系统</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Native%E5%BC%80%E5%8F%91"><span class="toc-number">3.5.</span> <span class="toc-text">Native开发</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86"><span class="toc-number">4.</span> <span class="toc-text">版本管理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%80%9A%E7%94%A8%E9%85%8D%E7%BD%AE"><span class="toc-number">5.</span> <span class="toc-text">通用配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99"><span class="toc-number">6.</span> <span class="toc-text">参考资料</span></a></li></ol></div></div><script defer="defer" data-pjax="data-pjax" src="/blog/js/card_clock.js"></script><div class="card-widget card-clock"><div id="clock"><img v-if="clockshow == &quot;false&quot;" alt="" src= "" data-lazy-src="/blog/img/weather/loading.gif" height="120px" width="100%"/><table class="clock" v-if="clockshow"><tbody><tr><td class="clockdate">{{date}}</td><td class="weatherimg"><img id="weatherimg" :src="weatherimg" alt=""/></td><td class="temperature">{{temperature}}</td><td class="humidityimg"><img id="humidityimg" :src="humidityimg" alt=""/></td><td class="humidity">{{humidity}}</td></tr><tr class="time"><td colspan="5">{{time}}</td></tr><tr><td class="usaqi" colspan="1"><span>{{ip}}</span></td><td class="city" colspan="2">{{city}}</td><td class="daylight" colspan="2">{{daylight}}</td></tr></tbody></table></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/blog/2021/05/24/tools/hexo/advanced/" title="Hexo 博客页面性能优化"><img src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/Hexo-logo.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="Hexo 博客页面性能优化"/></a><div class="content"><a class="title" href="/blog/2021/05/24/tools/hexo/advanced/" title="Hexo 博客页面性能优化">Hexo 博客页面性能优化</a><time datetime="2021-05-23T16:00:00.000Z" title="发表于 2021-05-24 00:00:00">2021-05-24</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2021/05/14/vue/vue-code-9.event/" title="（Vue源码七）Vue 事件"><img src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/components.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="（Vue源码七）Vue 事件"/></a><div class="content"><a class="title" href="/blog/2021/05/14/vue/vue-code-9.event/" title="（Vue源码七）Vue 事件">（Vue源码七）Vue 事件</a><time datetime="2021-05-13T16:00:00.000Z" title="发表于 2021-05-14 00:00:00">2021-05-14</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2021/05/04/vue/vue-code-8.component/" title="（Vue源码六）Vue 组件原理分析"><img src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/components.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="（Vue源码六）Vue 组件原理分析"/></a><div class="content"><a class="title" href="/blog/2021/05/04/vue/vue-code-8.component/" title="（Vue源码六）Vue 组件原理分析">（Vue源码六）Vue 组件原理分析</a><time datetime="2021-05-03T16:00:00.000Z" title="发表于 2021-05-04 00:00:00">2021-05-04</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2021/04/30/vue/vue-code-7-compiler/" title="（Vue源码五）Vue 编译原理"><img src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/vuetemplate.jpg" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="（Vue源码五）Vue 编译原理"/></a><div class="content"><a class="title" href="/blog/2021/04/30/vue/vue-code-7-compiler/" title="（Vue源码五）Vue 编译原理">（Vue源码五）Vue 编译原理</a><time datetime="2021-04-29T16:00:00.000Z" title="发表于 2021-04-30 00:00:00">2021-04-30</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/blog/2021/04/27/vue/vue-code-6.reactive/" title="（Vue源码四）数据响应式原理"><img src= "" data-lazy-src="https://gitee.com/FIF/pic-beg/raw/master/images/vue/mvvm.png" onerror="this.onerror=null;this.src='/blog/img/404.jpg'" alt="（Vue源码四）数据响应式原理"/></a><div class="content"><a class="title" href="/blog/2021/04/27/vue/vue-code-6.reactive/" title="（Vue源码四）数据响应式原理">（Vue源码四）数据响应式原理</a><time datetime="2021-04-26T16:00:00.000Z" title="发表于 2021-04-27 00:00:00">2021-04-27</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2021 By 志非</div><div class="footer_custom_text">Hi, welcome to my <a href="/">blog</a>!</div><div id="workboard"></div><script async="async" src="/blog/js/runtime.js"></script></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="chat_btn" type="button" title="rightside.chat_btn"><i class="fas fa-sms"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="algolia-search"><div class="search-dialog"><div class="search-dialog__title" id="algolia-search-title">Algolia</div><div id="algolia-input-panel"><div id="algolia-search-input"></div></div><hr/><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-stats"></div></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="https://cdn.jsdelivr.net/npm/vue"></script><script src="/blog/js/utils.js"></script><script src="/blog/js/main.js"></script><script src="/blog/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><script src="/blog/js/search/algolia.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><script>if (document.getElementsByClassName('mermaid').length) {
  if (window.mermaidJsLoad) mermaid.init()
  else {
    getScript('https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js').then(() => {
      window.mermaidJsLoad = true
      mermaid.initialize({
        theme: 'default',
      })
      false && mermaid.init()
    })
  }
}</script><script>function loadValine () {
  function initValine () {
    const valine = new Valine(Object.assign({
      el: '#vcomment',
      appId: 'JC72d1A7XBwC26rGCKMVn5CS-MdYXbMMI',
      appKey: 'xI6bG7FseICz8ShKdmWVe7N1',
      placeholder: 'Please leave your footprints',
      avatar: 'https://gitee.com/FIF/pic-beg/raw/master/images/vue/1619248532079-avatar_coment.webp',
      meta: 'nick,mail,link'.split(','),
      pageSize: '10',
      lang: 'zh-CN',
      recordIP: false,
      serverURLs: '',
      emojiCDN: '',
      emojiMaps: "",
      enableQQ: true,
      path: window.location.pathname,
      requiredFields: ["nick,mail"],
      visitor: false,
      avatar_cdn: 'https://www.gravatar.com/avatar/'
    }, null))
  }

  if (typeof Valine === 'function') initValine() 
  else getScript('https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js').then(initValine)
}

if ('Valine' === 'Valine' || !true) {
  if (true) btf.loadComment(document.getElementById('vcomment'),loadValine)
  else setTimeout(loadValine, 0)
} else {
  function loadOtherComment () {
    loadValine()
  }
}</script></div><div class="aplayer no-destroy" data-id="000PeZCQ1i4XVs" data-server="tencent" data-type="artist" data-fixed="true" data-mini="true" data-listFolded="false" data-order="random" data-preload="none" data-autoplay="false" pjax="true" muted></div><script defer="defer" id="ribbon" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-ribbon.min.js" size="150" alpha="0.6" zIndex="-1" mobile="false" data-click="true"></script><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = true;
POWERMODE.mobile = false;
document.body.addEventListener('input', POWERMODE);
</script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>